﻿#include "PluginMgr.h"
#include "boost/filesystem/path.hpp"
#include "boost/filesystem/operations.hpp"
#include "boost/locale.hpp"

DllCameraPlugin::~DllCameraPlugin()
{
#if 0
	if (m_hmod != NULL) FreeLibrary(m_hmod);
#endif

}

DllCameraPlugin::DllCameraPlugin(const std::wstring& modname)
:CameraPlugin(), m_plugin(NULL)
{
	wstring filename = modname;

#if 0
	m_hmod = LoadLibrary(filename.c_str());
	if (m_hmod != NULL)
	{
		m_proc = (PluginProc)GetProcAddress(m_hmod, CAMERA_PLUGIN_ENTRY_NAME);
		if (m_proc != NULL)
		{
			try{
				m_plugin = (CameraPlugin*)m_proc(CAMERA_PLUGIN_INTERFACE_VERSION);
				map_key = GetCameraBasic(m_plugin);
			}
			catch (std::exception){
				_err = L"插件执行过程中发生SEH异常";
			}
			if (m_plugin == NULL){
				_err = L"无法实例化插件 " + filename + L" 对象，接口版本不匹配";
			}
			else{
				_err = L"成功实例化插件" + filename;
			}
		}
		else{
			_err = L"无法定位插件 " + filename + L" 的入口函数";
		}
	}
	else{
		_err = L"无法载入插件 " + filename;
	}

#else
	std::string anSiNam = boost::locale::conv::utf_to_utf<char>(modname);
	if (m_loader.Open(anSiNam))
	{
		m_proc = (PluginProc)m_loader.GetProc(CAMERA_PLUGIN_ENTRY_NAME);
		if (m_proc != NULL)
		{
			try {
				m_plugin = (CameraPlugin*)m_proc(CAMERA_PLUGIN_INTERFACE_VERSION);
				map_key = GetCameraBasic(m_plugin);
			}
			catch (std::exception) {
				_err = wstring(L"插件执行过程中发生SEH异常");
			}

			if (m_plugin == NULL)
			{
				_err = wstring(L"无法实例化插件:") + filename + wstring(L" 对象，接口版本不匹配");
			}
			else
			{
				_err = wstring(L"成功实例化插件:") + filename;
			}
		}
		else
		{
			_err = wstring(L"无法定位插件:") + filename + wstring(L" 的入口函数");
		}
	}
	else
	{
		_err = wstring(L"无法载入插件:") + filename + wstring(L",Detail:") + m_loader.WGetLastErrorMsg();
	}

#endif
}

std::vector<CameraInterface*>& DllCameraPlugin::GetSupportInterface()
{
	return m_plugin->GetSupportInterface();
}
bool DllCameraPlugin::Inited()
{
	return m_plugin->Inited();
}
void DllCameraPlugin::Close()
{
	return m_plugin->Close();
}
std::wstring &DllCameraPlugin::GetError()
{
	return _err;
}
bool DllCameraPlugin::AddInterface(CameraInterface *_interface)
{
	return m_plugin->AddInterface(_interface);
}
bool DllCameraPlugin::Connect(int device_id, int ccd_serial, string mode)
{
	return m_plugin->Connect(device_id, ccd_serial, mode);
}
std::string DllCameraPlugin::GetEndCode()
{
	return m_plugin->GetEndCode();
}
std::string DllCameraPlugin::GetStartCode()
{
	return m_plugin->GetStartCode();
}
long DllCameraPlugin::GetSerialRate()
{
	return m_plugin->GetSerialRate();
}
void DllCameraPlugin::DisConnect()
{
	m_plugin->DisConnect();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CameraPluginMgr::CameraPluginMgr()
{
	cameras.clear();
	RescanPlugins();
}

CameraPluginMgr::~CameraPluginMgr()
{
	for (std::map<wstring, CameraPlugin*>::iterator it = cameras.begin(); it != cameras.end(); it++){
		it->second->Close();
		delete it->second;
	}
	cameras.clear();
}

int CameraPluginMgr::RescanPlugins()
{
	string fullpath = boost::filesystem::initial_path<boost::filesystem::path>().string();
#ifdef __LINUX__
	fullpath += "/Cameras/";
#else
	fullpath += "\\Cameras\\";
#endif
	cout << "[pluginmgr] Decoder plugin path = " << fullpath << endl;
	boost::filesystem::path full_path(fullpath
#ifndef __LINUX__
		, boost::filesystem::native
#endif
		);
	if (boost::filesystem::exists(full_path)){
		for (boost::filesystem::directory_iterator item_begin(full_path); item_begin != boost::filesystem::directory_iterator(); item_begin++){
			if (boost::filesystem::is_regular_file(*item_begin))
			{
				wstring file_name = item_begin->path().wstring();
				if (file_name.find(DLL_SUFFIX) != std::string::npos) {
					wcout << "[pluginmgr] " << file_name << endl;
					DllCameraPlugin *camera = new DllCameraPlugin(file_name);
					if (camera && camera->Inited()){
						cameras[camera->map_key] = camera;
					}
				}
			}
		}
	}
	return cameras.size();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
std::wstring GetCameraBasic(CameraPlugin *plugin)
{
	std::vector<CameraInterface*>& interfaces = plugin->GetSupportInterface();
	for (auto it = interfaces.begin(); it != interfaces.end(); it++) {
		if ((*it)->GetName() == CameraKeyInterfaceName) {
			std::wstring camera_basic;
			CAM_INTERFACE_VALUE_TYPE value;
			SubInterface *sub_interface = (*it)->GetSubInterface(CameraKeySubInterfaceName);
			if (sub_interface) {
				sub_interface->Get(value);
				camera_basic += boost::get<std::wstring>(value);
			}
			return camera_basic;
		}
	}
	return L"NOT STANDARD CAMERA";
}

